package game.data;

import echo.Body;
import echo.shape.Polygon;
import hx.geom.Rectangle;
import game.worlds.World;
import game.worlds.IAttackDisplay;
import game.worlds.GameRole;
import echo.Shape;

/**
 * 帧数据
 */
@:build(game.macro.FrameDataMacro.build())
class FrameData implements ICopy {
	/**
	 * 所在帧ID
	 */
	public var frame:Int = 0;

	/**
	 * 事件标签
	 */
	public var eventTag:String;

	/**
	 * 精灵图名称
	 */
	public var name:String;

	/**
	 * 原始位移X
	 */
	public var originMoveX:Null<Float> = null;

	/**
	 * 原始位移Y
	 */
	public var originMoveY:Null<Float> = null;

	/**
	 * 原始锚点X
	 */
	public var originPointX:Null<Float> = null;

	/**
	 * 原始锚点Y
	 */
	public var originPointY:Null<Float> = null;

	/**
	 * 原点缩放X
	 */
	public var originScaleX:Null<Float> = null;

	/**
	 * 原点缩放Y
	 */
	public var originScaleY:Null<Float> = null;

	/**
	 * 原始角度
	 */
	public var originRotate:Null<Float> = null;

	/**
	 * 原始透明度
	 */
	public var originAlpha:Null<Float> = null;

	/**
	 * 帧碰撞数据，如果帧存在碰撞数据时，则在战斗过程中，会产生攻击效果
	 */
	public var collision:Body;

	/**
	 * 震动强度
	 */
	public var shakeIntensity:Float = 0;

	/**
	 * 震动持续时间
	 */
	public var shakeDuration:Float = 0;

	/**
	 * 震动频率
	 */
	public var shakeFrequency:Float = 10;

	/**
	 * 发起震动效果
	 * @param world 
	 */
	public function shake(world:World):Void {
		if (shakeDuration > 0 && shakeIntensity > 0)
			world.camera.shakeManager.addShake(shakeIntensity, shakeDuration, shakeFrequency);
	}

	/**
	 * 测试碰撞
	 * @param role 碰撞触发对象
	 * @param collider 被检测碰撞对象
	 * @return Bool
	 */
	public function testCollision(role:IAttackDisplay, collider:Shape):Bool {
		this.collision.scale_x = role.scaleX * role.getRole().assets.data.attrData.getBodyScale();
		this.collision.scale_y = role.scaleY * role.getRole().assets.data.attrData.getBodyScale();
		this.collision.x = role.x;
		this.collision.y = role.y;
		this.collision.rotation = role.rotation;
		for (shape in collision.shapes) {
			var ret = shape.collides(collider);
			if (ret != null) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 帧碰撞有效时间
	 */
	public var collisionLiveTime:Float = 0;

	/**
	 * 击中效果
	 */
	public var hitData:HitData = new HitData();

	/**
	 * 该帧需要停顿
	 */
	public var isStop:Bool = false;

	/**
	 * 停顿动作
	 */
	public var stopAction:String = null;

	/**
	 * 特效渲染数据
	 */
	public var effects:Array<EffectData> = [];

	/**
	 * 原始时间轴
	 */
	public var timeline:ITimelineData;

	/**
	 * 无敌时间
	 */
	public var invincibleTime:Float = 0;

	/**
	 * 霸体时间
	 */
	public var stoicTime:Float = 0;

	/**
	 * 共享碰撞，即沿用上一次的碰撞数据，仅更新碰撞数据
	 */
	public var shareCollision:Bool = false;

	/**
	 * 追加特效
	 * @param effect 
	 */
	public function addEffect(effect:EffectData) {
		effects.push(effect);
		effect.frameData = this;
	}

	/**
	 * 删除特效
	 * @param effect 
	 */
	public function removeEffect(effect:EffectData) {
		effects.remove(effect);
		effect.frameData = null;
	}

	/**
	 * 播放音效
	 */
	public var sound:String;

	public function new() {}

	public function clone():FrameData {
		var frameData:FrameData = new FrameData();
		frameData.name = this.name;
		return frameData;
	}

	public function copy():FrameData {
		var frameData:FrameData = new FrameData();
		frameData.name = this.name;
		for (field in Reflect.fields(this)) {
			if (field == "timeline")
				continue;
			if (field == "effects") {
				frameData.effects = [
					for (data in this.effects) {
						data.clone();
					}
				];
			} else if (field == "hitData") {
				frameData.hitData = this.hitData.clone();
			} else {
				Reflect.setProperty(frameData, field, Reflect.getProperty(this, field));
			}
		}
		return frameData;
	}

	/**
	 * 获得攻击块的矩形
	 * @param role 
	 * @return Rectangle
	 */
	public function getRectangleByRole(role:GameRole):Rectangle {
		var rect = new Rectangle();
		for (shape in collision.shapes) {
			if (shape is Polygon) {
				var p:Polygon = cast shape;
				for (vector in p.vertices) {
					rect.expand(vector.x * role.scaleX + role.x, vector.y + role.y, 1, 1);
				}
			}
		}
		return rect;
	}
}
